package cn.kk.lucene.index;

import java.nio.file.Path;
import java.nio.file.Paths;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.IntPoint;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanClause.Occur;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.PhraseQuery;
import org.apache.lucene.search.PrefixQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.junit.Test;

import cn.kk.lucene.IK.IKAnalyzer6x;

public class SearchIndex2 {
	/**
	 * 布尔查询
	 * 组合的query,和确定多个query之间的逻辑关系,返回查询结果
	 * @throws Exception
	 */
	@Test
	public void booleanQuery() throws Exception {
		// 1 路径
		Path path = Paths.get("indexdir");
		Directory dir = FSDirectory.open(path);
		// 2 搜索对象创建searcher
		// 对接一个输入流
		IndexReader reader = DirectoryReader.open(dir);
		IndexSearcher searcher = new IndexSearcher(reader);
		// 搜索使用的分词器IK
		Analyzer analyzer = new IKAnalyzer6x();

		// TODO 词项查询条件
		// 设置多个查询的条件对象
		Query query1 = new TermQuery(new Term("title", "测试"));
		Query query2 = new TermQuery(new Term("data", "城"));
		// 指定逻辑关系,title有苹果,sellpiont没平板
		BooleanClause bc1 = new BooleanClause(query1, Occur.MUST);
		BooleanClause bc2 = new BooleanClause(query2, Occur.MUST_NOT);
		BooleanQuery query = new BooleanQuery.Builder().add(bc1).add(bc2).build();

		System.out.println("query条件:" + query.toString());
		// 4 获取数据for循环遍历;默认情况下,每个doc返回时
		// 封装到一个topDoc的对象中,底层包装了一个数组,评分
		// doc;循环数组,调用api获取数据
		TopDocs topDoc = searcher.search(query, 10);// 返回所有数据前10条
		// 封装了获取doc的所有条件的docs对象
		ScoreDoc[] docs = topDoc.scoreDocs;
		for (int i = 0; i < docs.length; i++) {
			// 获取document的文件
			Document document = searcher.doc(docs[i].doc);
			System.out.println("id:" + document.get("id"));
			System.out.println("title:" + document.get("title"));
			System.out.println("data:" + document.get("data"));

		}

	}

	/*
	 * 范围查询, 必须对应具有intPoint longPoint的文档数据
	 */
	@Test
	public void rangeSearch() throws Exception {
		// 1 路径
		Path path = Paths.get("indexdir");
		Directory dir = FSDirectory.open(path);
		// 2 搜索对象创建searcher
		// 对接一个输入流
		IndexReader reader = DirectoryReader.open(dir);
		IndexSearcher searcher = new IndexSearcher(reader);
		// 搜索使用的分词器IK
		Analyzer analyzer = new IKAnalyzer6x();

		// TODO 词项查询条件
		Query query = IntPoint.newRangeQuery("word", 0, 10);

		System.out.println("query条件:" + query.toString());
		// 4 获取数据for循环遍历;默认情况下,每个doc返回时
		// 封装到一个topDoc的对象中,底层包装了一个数组,评分
		// doc;循环数组,调用api获取数据
		TopDocs topDoc = searcher.search(query, 10);// 返回所有数据前10条
		// 封装了获取doc的所有条件的docs对象
		ScoreDoc[] docs = topDoc.scoreDocs;
		for (int i = 0; i < docs.length; i++) {
			// 获取document的文件
			Document document = searcher.doc(docs[i].doc);
			System.out.println("id:" + document.get("id"));
			System.out.println("title:" + document.get("title"));
			System.out.println("data:" + document.get("data"));

		}
	}

	/*
	 * 前缀查询
	 */
	@Test
	public void prefixSearch() throws Exception {
		// 1 路径
		Path path = Paths.get("indexdir");
		Directory dir = FSDirectory.open(path);
		// 2 搜索对象创建searcher
		// 对接一个输入流
		IndexReader reader = DirectoryReader.open(dir);
		IndexSearcher searcher = new IndexSearcher(reader);
		// 搜索使用的分词器IK
		Analyzer analyzer = new IKAnalyzer6x();

		// TODO 词项查询条件
		Term term = new Term("title", "测试");
		Query query = new PrefixQuery(term);
		System.out.println("query条件:" + query.toString());
		// 4 获取数据for循环遍历;默认情况下,每个doc返回时
		// 封装到一个topDoc的对象中,底层包装了一个数组,评分
		// doc;循环数组,调用api获取数据
		TopDocs topDoc = searcher.search(query, 10);// 返回所有数据前10条
		// 封装了获取doc的所有条件的docs对象
		ScoreDoc[] docs = topDoc.scoreDocs;
		for (int i = 0; i < docs.length; i++) {
			// 获取document的文件
			Document document = searcher.doc(docs[i].doc);
			System.out.println("id:" + document.get("id"));
			System.out.println("title:" + document.get("title"));
			System.out.println("data:" + document.get("data"));
		}

	}

	/*
	 * 多关键字查询
	 * 
	 */
	@Test
	public void mutiTermQuery() throws Exception {
		// 1 路径
		Path path = Paths.get("indexdir");
		Directory dir = FSDirectory.open(path);
		// 2 搜索对象创建searcher
		// 对接一个输入流
		IndexReader reader = DirectoryReader.open(dir);
		IndexSearcher searcher = new IndexSearcher(reader);
		// 搜索使用的分词器IK
		Analyzer analyzer = new IKAnalyzer6x();

		// TODO 多关键字查询
		PhraseQuery.Builder build = new PhraseQuery.Builder();
		// 添加多个关键字
		build.add(new Term("data", "国"));
		build.add(new Term("data", "破"));
		build.add(new Term("data", "山河"));
		PhraseQuery query = build.build();

		System.out.println("query条件:" + query.toString());
		// 4 获取数据for循环遍历;默认情况下,每个doc返回时
		// 封装到一个topDoc的对象中,底层包装了一个数组,评分
		// doc;循环数组,调用api获取数据
		TopDocs topDoc = searcher.search(query, 10);// 返回所有数据前10条
		// 封装了获取doc的所有条件的docs对象
		ScoreDoc[] docs = topDoc.scoreDocs;
		for (int i = 0; i < docs.length; i++) {
			// 获取document的文件
			Document document = searcher.doc(docs[i].doc);
			System.out.println("id:" + document.get("id"));
			System.out.println("title:" + document.get("title"));
			System.out.println("data:" + document.get("data"));

		}
	}

}
